<?php
##
# 醒置器
# 大多数程序都会有个数据文件,但修改数据的时候却没有一个图形化的工具.
# 本数据器将解决这一问题.
##

##
# 实现原理:
# 这里假设程序的数据以数组形式保存.
# 添加数据即是添加一个数组的键名.
# 修改数组某个数据即是修改数组指键名的元素的值.
# 删除某个数据项即是删除数组的某个元素.
##


class Data
{
    protected $data = array();
    protected $msg;
    protected $dataPath;
    protected $modified=false; //标记数据是否已经被修改,如果被修改,那么将自保存修改
    static protected $instances = array();

    /**
     * 声明类时加载数据文件
     */
    protected function __construct($dataPath)
    {
        if(!is_file($dataPath)){
            $this->setMsg("$dataPath 不存在");
        }else{
            $this->load($dataPath);
        }
    }

    public function __destruct()
    {
        if($this->modified)
            $this->save();
    }

    public function getInstance($dataPath)
    {
        if(!isset(self::$instances[$dataPath])){
            self::$instances[$dataPath] = new self($dataPath);;
        }
        return self::$instances[$dataPath];
    }

    /**
     * 加载数据文件
     * @param string $dataPath 数据文件所在的路径
     */
    public function load($dataPath)
    {
        filesize($dataPath)==0 && file_put_contents($dataPath, "<?php return array('___locked'=>null,);");
        !is_array($this->data) && $this->data = array();
        $dataPath = realpath($dataPath);
        $this->data = include_once($dataPath);
        $this->dataPath = $dataPath;
    }

    /**
     * 保存或更新数据
     */
    public function save()
    {
        !is_array($this->data) && $this->data = array();
        $content = var_export($this->data, 1);
        $content = "<?php\r\nreturn $content;";
        return file_put_contents($this->dataPath, $content);
    }

    /**
     * 锁定某个数据项,不允再修改它
     * @param string $key 待锁定的项
     * @return bool
     */
    public function lockKey($key)
    {
        return $this->data["___locked"][$key] = true;
    }

    public function unlockKey($key)
    {
        unset($this->data["___locked"][$key]);
    }


    /**
     * __set魔术函数,它将添加或修改数据项
     * 如果被修改的数据项已经被锁定,那么将会导引错误,修改失败
     * @param string $key 数据项的名称
     * @param string $val 项置项的值
     */
    public function __set($key, $val)
    {
        if(isset($this->data["___locked"][$key]) && $this->data["___locked"][$key] == true){
            $this->setMsg("[$key] 已经被锁定,不能修改");
        }else{
            $this->data[$key] = $val;
            $this->modified = true;
        }
    }

    /**
     * 获得数据项的值
     */
    public function __get($key)
    {
        if(isset($this->data[$key])){
            return $this->data[$key];
        }else{
            $this->setMsg("不存在此项 [$key]");
        }
    }

    /**
     * 删除数据项
     */
    public function __unset($key)
    {
        unset($this->data[$key]);
        $this->modified = true;
        return !isset($this->data[$key]);
    }

    private function setMsg($msg)
    {
        $this->msg = $msg;
    }
}

$data = new Data("./33.txt");

$data->name = "hello";